package protocol

import (
	"bytes"
	"encoding/binary"
	"unsafe"

	"google.golang.org/protobuf/proto"
	"test.com/src/msgcmd"
)

func BuildMsg(cmd uint32, body []byte) ([]byte, error) {
	msgLen := len(body)
	len := int(unsafe.Sizeof(cmd))

	buf := make([]byte, len)
	data := bytes.NewBuffer(buf)
	data.Reset()

	binary.Write(data, binary.BigEndian, cmd)
	if msgLen > 0 {
		binary.Write(data, binary.BigEndian, body)
	}
	return data.Bytes(), nil
}

func BuildChangeNameReq(name string) ([]byte, error) {
	msg := &ChangeNameReq{Name: &name}
	body, _ := proto.Marshal(msg)
	return BuildMsg(msgcmd.ChangeNameReq, body)
}

func BuildChangeNameRsp(result bool, name string, errMsg string) ([]byte, error) {
	msg := &ChangeNameRsp{Result: &result, Name: &name, ErrMsg: &errMsg}
	body, _ := proto.Marshal(msg)
	return BuildMsg(msgcmd.ChangeNameRsp, body)
}

func BuildChatMsg(sender string, txt string) ([]byte, error) {
	msg := &ChatMsg{Txt: &txt, Sender: &sender}
	body, _ := proto.Marshal(msg)
	return BuildMsg(msgcmd.ChatMsg, body)
}

func BuildRoomListMsg(count uint32) ([]byte, error) {
	msg := &RoomListMsg{Count: &count}
	body, _ := proto.Marshal(msg)
	return BuildMsg(msgcmd.RoomListMsg, body)
}

func BuildPlayerInRsp(result bool, roomId uint32, msgs []string) ([]byte, error) {
	msg := &PlayerInRsp{Result: &result, RoomId: &roomId}
	if msgs != nil && len(msgs) > 0 {
		msg.Msgs = append(msg.Msgs, msgs...)
	}
	body, _ := proto.Marshal(msg)
	return BuildMsg(msgcmd.PlayerInRsp, body)
}

func DecodeCmd(buf []byte) (uint32, *bytes.Buffer) {
	var cmd uint32
	data := bytes.NewBuffer(buf)
	binary.Read(data, binary.BigEndian, &cmd)
	return cmd, data
}

func DecodeChat(msg *bytes.Buffer) *ChatMsg {
	ret := ChatMsg{}
	proto.Unmarshal(msg.Bytes(), &ret)
	return &ret
}

func DecodePlayerInReq(msg *bytes.Buffer) *PlayerInReq {
	ret := PlayerInReq{}
	proto.Unmarshal(msg.Bytes(), &ret)
	return &ret
}

func DecodeRoomList(msg *bytes.Buffer) *RoomListMsg {
	ret := RoomListMsg{}
	proto.Unmarshal(msg.Bytes(), &ret)
	return &ret
}

func DecodePlayerInRsp(msg *bytes.Buffer) *PlayerInRsp {
	ret := PlayerInRsp{}
	proto.Unmarshal(msg.Bytes(), &ret)
	return &ret
}

func DecodeChangeNameReq(msg *bytes.Buffer) *ChangeNameReq {
	ret := ChangeNameReq{}
	proto.Unmarshal(msg.Bytes(), &ret)
	return &ret
}

func DecodeChangeNameRsp(msg *bytes.Buffer) *ChangeNameRsp {
	ret := ChangeNameRsp{}
	proto.Unmarshal(msg.Bytes(), &ret)
	return &ret
}
